package pers.cz.jefconfig.resource;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.Arrays;
import java.util.List;

/**
 * @program: JefConfig
 * @description: 资源工具
 * @author: Cheng Zhi
 * @create: 2022-07-14 17:26
 **/
public class ResourceUtil {

    private static final JefResourceLoader classPathResourceLoader = new UrlResourceLoader(UrlResourceLoader.EnvURL.JAVA_CLASS_PATH);
    private static final JefResourceLoader userDirResourceLoader = new UrlResourceLoader(UrlResourceLoader.EnvURL.USER_DIR);
    private static final JefResourceLoader dirOnlyResouceLoader = new ClassPathResourceLoader(true);
    private static final JefResourceLoader defaultResouceLoader = new ClassPathResourceLoader(false);

    public static List<URL> getResources(String name) {
        return getResources(name, false);
    }

    /**
     * 在指定的路径上查找资源文件 从生产实践讲，放在目录下的文件由于便于维护，比放在JAR包中的文件享有绝对优先权。
     *
     * @param name
     *            资源名称，资源名称可以采用下列格式之一
     *            <table width=90% border=1>
     *            <tr>
     *            <td>resource-path/name</td>
     *            <td width="80%">即classpath下的resource-path/name资源</td>
     *            </tr>
     *            <tr>
     *            <td>/resource-path/name</td>
     *            <td>第一个斜杠会自动被忽略，结果同上(请避免这样用)</td>
     *            </tr>
     *            <tr>
     *            <td>classpath*:resource-path/name</td>
     *            <td>“classpath*:”会被忽略，结果同上</td>
     *            </tr>
     *            <tr>
     *            <td>classpath:resource-path/name</td>
     *            <td>“classpath:” 会被忽略，结果同上</td>
     *            </tr>
     *            <tr>
     *            <td>file:resource-path/name</td>
     *            <td>会在当前程序运行目录下寻找资源</td>
     *            </tr>
     *
     *            <tr>
     *            <td>file:/resource-path/name</td>
     *            <td>第一个斜杠会自动被忽略，结果同上</td>
     *            </tr>
     *            <tr>
     *            <td>file://c:/resource-path/name</td>
     *            <td>第一个斜杠被忽略，第二个斜杠表明这是绝对路径，按绝对路径查找文件</td>
     *            </tr>
     *            <tr>
     *            <td>http://localhost:80/context/name</td>
     *            <td>直接以这个URL作为资源</td>
     *            </tr>
     *            <tr>
     *            <td>ftp://user:password@host:21/name</td>
     *            <td>直接以这个URL作为资源</td>
     *            </tr>
     *            </table>
     * @param dironly
     *            为true只查找目录中的资源，放弃jar包或zip包的资源，以及http等网络资源(仅当查找classpath类资源有效)
     * @param classLoaders
     *            指定类加载器，将使用这些类加载器来查找资源 (仅当查找classpath类资源有效)
     * @return
     */
    public static List<URL> getResources(String name, boolean dironly, ClassLoader... classLoaders) {

        if (name.startsWith("classpath*:")) {
            name = name.substring(11);
        } else if (name.startsWith("classpath:")) {
            name = name.substring(10);
        } else if (name.startsWith("file:")) {
            name = name.substring(5);
            URL u = userDirResourceLoader.getResource(name);
            if (u != null) {
                return Arrays.asList(u);
            } else {
                return Arrays.asList();
            }
        } else if (name.indexOf("://") > -1) {
            try {
                URL u = new URL(name);
                return Arrays.asList(u);
            } catch (MalformedURLException e) {
                throw new IllegalArgumentException(name + " is invalid! " + e.getMessage());
            }
        }

        if (classLoaders.length == 0) {
            return dironly ? dirOnlyResouceLoader.getResources(name) : defaultResouceLoader.getResources(name);
        }

        return null;
    }

}
